using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Jasongozy.Copor;
using System.Xml;
using Jasongozy.Copor.Utility;
namespace Copor.Test.UnitTest {
    [TestFixture]
    public class FunctionTest {

        private TableSchema InitMockSchema() {
            TableSchema schema = new TableSchema();
            schema.TableName = "table1";
            schema.Pks = new string[] { "c1", "c2" };
            schema.Columns = new string[] { "c1", "c2", "c3" };
            schema.ColumnTypes = new string[] { "System.String", "System.String", "System.Int32" };
            schema.DefaultValues = new Dictionary<string, string>();
            schema.DefaultValues.Add("c1", "xxxx1");
            return schema;
        }
        [Test]
        public void SampleDemoTest() {
            string content = "${cell} AS {@OutputPrefix}.${cell}";
            int length = 3;
            string tempVar = "cell";
            bool onlyOneLine = true;
            string split = ",";
            string collectionKey = "Columns";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++) {
                if (onlyOneLine) {
                    string newContent = content.Replace("${" + tempVar + "}", "{$" + collectionKey + "[" + i + "]}");
                    sb.Append(newContent);
                    sb.AppendLine(split);
                }
            }
            Console.WriteLine(sb.ToString());

        }

        [Test]
        public void LoopFunctionTest() {
            Dictionary<string, string> property = new Dictionary<string, string>();
            TableSchema schame = InitMockSchema();

            TemplateParameter.InitTemplateParameter(schame, null, null, "Csharp", "mysql", "sqltxt");
            property["content"] = "${cell} AS r_${cell}";
            property["source"] = "{$Columns}";
            property["split"] = ",";
            property["only-one-line"] = "false";
            property["param"] = "${cell}";

            LoopFuncation loopFunc = new LoopFuncation();
            loopFunc.IniteProperty(property);
            string res = loopFunc.Execute();
            Console.WriteLine(res);

            Console.WriteLine("===========================");

            property.Remove("param");
            property["content"] = "group.{$Columns[${i}]} = ({$ColumnTypes[${i}]}) reader[\"r_{$Columns[${i}]}\"]";
            property["index"] = "${i}";


            loopFunc.IniteProperty(property);
            res = loopFunc.Execute();
            Console.WriteLine(res);
        }


        [Test]
        public void ColumnTypeFuncTest() {
            Dictionary<string, string> property = new Dictionary<string, string>();
            TableSchema schema = InitMockSchema();

            TemplateParameter.InitTemplateParameter(schema, null, null, "Csharp", "mysql", "sqltxt");
            //property["content"] = "${cell} AS r_${cell}";
            property["source"] = "{$ColumnTypes}";
            property["args"] = "1";

            IsValueTypeFunction func = new IsValueTypeFunction();
            func.IniteProperty(property);
            string res = func.Execute();
            Console.WriteLine(res);

            Console.WriteLine("===========================");
            property["args"] = "2";

            func.IniteProperty(property);
            res = func.Execute();
            Console.WriteLine(res);

        }

        [Test]
        public void GetValueForProcParamFunctionTest() {
            Dictionary<string, string> property = new Dictionary<string, string>();
            TableSchema schema = InitMockSchema();
            string connection = "Server=10.2.6.47;uid=DMClient;pwd=2Fetch(Get;allow zero datetime=no;pooling=true;charset=utf8;database=PeopleData;";
            string dbName = "PeopleData";
            TemplateParameter.InitTemplateParameter(schema, connection, dbName, "Csharp", "mysql", "sqltxt");
            property["args"] = "p_c3,p_,the";
            property["source"] = "{$ColumnTypes}";
            GetValueForProcParamFunction func = new GetValueForProcParamFunction();
            func.IniteProperty(property);
            string res = func.Execute();
            Console.WriteLine(res);
            property["args"] = "p_c1,p_,the";
            func.IniteProperty(property);
            res = func.Execute();
            Console.WriteLine(res);
        }


        [Test]
        public void funcCallFuncTest() {
            string xml = @" <TemplateRoot><TemplateItem Name='DataGroup'><TemplateItem Name='GetList'>

                <Content>
                    internal override {@DataGroupName}[] Get{@DataGroupName}ListByPK( {$ColumnType[0]}#{GetFullColumnType(#{IsValueType(0)})} {@MethodArgumentPrefix}{$Columns[0]}List, #{GetArgusForPK()}){
                    if({@MethodArgumentPrefix}{$Columns[0]}List == null) { throw  new DBGroupException('Argument is not valid!');
                    string ids = string.Join(',',{@MethodArgumentPrefix}{$Columns[0]}List);
                    List&lt;MySqlParameter&gt; ps = new List&lt;MySqlParameter&gt;();
                    #{GetAllParameters(get{$TableName}List)}
                    List&lt;{@DataGroupName}&gt; groups = List&lt;{@DataGroupName}&gt;();
                    string sqlCmd = string.Format('{{0}}.{{1}}',Names._DBName_,GetsStoredCommand);
                    using (MySqlDataReader reader = MySqlHelper2.ExecuteReader(AppConfigInfo.SqlConfig.GetConnectionString(DbName, DbInstanceName, 'Client'),System.Data.CommandType.StoredProcedure,sqlCmd,ps.ToArray())) {
                    while(reader.Read()){
                    {@DataGroupName} group = CreateDataGroup(reader);
                    FireGottenEvent(this,'Get{@DataGroupName}ListByPK',group);
                    groups.Add(group);
                    }
                    }
                    return groups.ToArray();
                    }
                </Content>
            </TemplateItem></TemplateItem>
<Functions>
             <Item Name='GetArgusForPK'>
            <Loop  source ='{$Columns}' only-one-line='true' split=',' index='${i}' start='1'>
                {$ColumnType[[${i}]}#{GetFullColumnType(#{IsValueType(${i})})} {@MethodArgumentPrefix}{$Columns[${i}]}
            </Loop>
        </Item>
        <Item Name='GetFullColumnType'>
            <If test='true'>
                ?
            </If>
        </Item>
        <Item Name='IsValueType'>
            <IsValueType source='{$ColumnTypes}'  />
        </Item>
        <Item Name='GetAllParameters'>
            <SqlProcParam param='${ParameterName},${MySqlDbType},${Direction},${Size},${Scale},${Precision}' >
                ps.Add(MySqlHelper2.MakeParameter('${ParameterName}',MySqlDbType.${MySqlDbType},ParameterDirection.${Direction},value,${Size},${Scale},${Precision}));
            </SqlProcParam>
        </Item></Functions>
 <Macros>
        <Item Name='Namespace'>CoporMock</Item>
        <Item Name='DataGroupName'>{$TableName}Group</Item>
        <Item Name='OutputPrefix'>r_</Item>
        <Item Name='InputPrefix'>p_</Item>
        <Item Name='MethodArgumentPrefix'>the</Item>
        <Item Name='PropertyArgumentPrefix'>this.</Item>
        <Item Name='InstanceArgument'>g.</Item>
    </Macros>
</TemplateRoot>
";
            TemplateNodeDefaultParser parser = new TemplateNodeDefaultParser();
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            TemplateTreeNode node = parser.Parse(doc);

            string connect = "Server=10.2.6.47;uid=DMClient;pwd=2Fetch(Get;allow zero datetime=no;pooling=true;charset=utf8;database=PeopleData;";
            string dbname = "PeopleData";
            TableSchema schema = MySqlDBHelper.GetTableSchema(connect, dbname, "CategoryAverageReturn");
            TemplateParameter.InitTemplateParameter(schema, connect, dbname, "Csharp", "mysql", "sqltxt");
            Analysis(node);
            Assert.AreEqual(true, node.HasChild);
            Console.WriteLine(DisplayTemplateTreeNode(node));
        }

        private static void Analysis(TemplateTreeNode node) {
            TemplateSyntax syn = new TemplateSyntax();
            if (node.TemplateNodeName == "GetList") {
                Console.WriteLine("1");
            }
            if (!node.HasChild) 
                syn.Analysis(node);
            else {
                foreach (TemplateTreeNode n in node.ChildNodes) {
                    Analysis(n);
                }
            }
        }

        private string DisplayTemplateTreeNode(TemplateTreeNode node) {
            StringBuilder code = new StringBuilder();
            code.AppendLine(node.TemplateContent);
            foreach (TemplateTreeNode subNode in node.ChildNodes) {
                code.AppendLine(DisplayTemplateTreeNode(subNode));
            }
            return code.ToString();
        }
    }
}
